﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;

namespace TlsService
{
    public class TlsUri
{
    private TlsConfig config;
    private TlsUser user;
    private TlsOperate operate;

    public TlsUri()
    {
        config = new TlsConfig();
        user = new TlsUser();
        operate = new TlsOperate();
    }

    public Uri Build()
    {
        string canonicalized = CanonicalizedQuery();
        string sign = Sign(canonicalized, user.secretKey);
        string wws = $"{config.wss}{user.appid}?{canonicalized}&signature={sign}";
        return new Uri(wws);
    }

    private string CanonicalizedQuery()
    {
        Dictionary<string, object> queryParamsMap = new Dictionary<string, object>();
        queryParamsMap.Add("convert_num_mode",1);
        queryParamsMap.Add("engine_model_type","16k_zh");
        queryParamsMap.Add("expired",operate.AfterDate);
        queryParamsMap.Add("filter_dirty",0);
        queryParamsMap.Add("filter_empty_result",1);
        queryParamsMap.Add("filter_modal",0);
        queryParamsMap.Add("filter_punc",0);
        queryParamsMap.Add("needvad",0);
        queryParamsMap.Add("nonce","2412454124");
        queryParamsMap.Add("reinforce_hotword",0);
        queryParamsMap.Add("secretid",user.secretId);
        queryParamsMap.Add("timestamp",operate.NowTime);
        queryParamsMap.Add("voice_format",1);
        queryParamsMap.Add("voice_id",operate.Uuid);
        queryParamsMap.Add("word_info",0);
        

        string[] sortedKeys = new List<string>(queryParamsMap.Keys).ToArray();
        Array.Sort(sortedKeys);
        string queryString = null;
        try
        {
            StringBuilder canonicalizedQueryString = new StringBuilder();
            foreach (string key in sortedKeys)
            {
                canonicalizedQueryString.Append("&").Append(PercentEncode(key)).Append("=")
                    .Append(PercentEncode(queryParamsMap[key].ToString()));
            }

            queryString = canonicalizedQueryString.ToString().Substring(1);
            return queryString;
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }

        return queryString;
    }

    private string PercentEncode(string param)
    {
        if (param != null)
        {
            var encodedValue = Uri.EscapeDataString(param);
            encodedValue = encodedValue.Replace("+", "%20");
            encodedValue = encodedValue.Replace("*", "%2A");
            encodedValue = encodedValue.Replace("%7E", "~");
            return encodedValue;
        }
        else
        {
            return null;
        }
    }

    public string Sign(string string2Sign, string accessKeySecret)
    {
        string body = $"{config.service}{user.appid}?{string2Sign}";
        byte[] key = Encoding.UTF8.GetBytes(accessKeySecret);
        using (HMACSHA1 hmac = new HMACSHA1(key))
        {
            byte[] messageBytes = Encoding.UTF8.GetBytes(body);
            byte[] hashMessageBytes = hmac.ComputeHash(messageBytes);
            string signBase64 = Convert.ToBase64String(hashMessageBytes);
            string signUrlEncode = Uri.EscapeDataString(signBase64);
            return signUrlEncode;
        }
    }
}
}
